using System;
using System.Text;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using GuavaData;
using GuavaLib;


namespace CORIDemo
//namespace GuavaLib
{
    public enum FindingProcType { COL, EGD, ERCP, FLX }

	public class DrawFindings : System.Windows.Forms.UserControl, GuavaQueryElement, GuavaLaunchBase
	{
		#region Proc Type

        private FindingProcType fpt;
        private BitmapSet bset;
        public FindingProcType ProcType
        {
            get
            {
                return this.fpt;
            }
            set
            {
                this.fpt = value;
                this.objPictureRegions = new PictureRegions(value);
                switch (value)
                {
                    case FindingProcType.COL:
                        this.bset = new COL_Bitmaps();
                        break;

                    case FindingProcType.EGD:
                        this.bset = new EGD_Bitmaps();
                        break;

                    case FindingProcType.ERCP:
                        this.bset = new ERCP_Bitmaps();
                        break;

                    case FindingProcType.FLX:
                        this.bset = new FLX_Bitmaps();
                        break;

                    default:
                        this.bset = null;
                        break;
                }

                if (this.bset != null)
                    this.CreateDrawing(bset.draw, bset.mask, bset.part);
            }
        }
		#endregion

        #region Fields

        private FindTags ftags;

		private Bitmap 
				bitClip,	// transparent mask to clip the brush drawing to the lines
				bitPart,	// drawing with parts in key colors
				bitMain,	// main drawing 
				bitHits;	// hit test for the mouse on the drawing
		private bool isDrawing;
		private short[] mousepoints;
		private int pointcount;
		private int regionBits;		// all regions that were drawn in
		private int regionClick;	// region of the initial click

		private Graphics pictGraph;
		private Graphics maskGraph;
		private SolidBrush dotBrush;
		private SolidBrush panBrush;
		private Pen pen;
		// mousedown sets these
		private int drawX = 0;
		private int drawY = 0;
		// mousedown or mousemove > quantum sets these
		private int lastX = 0;		
		private int lastY = 0;

		private int dType = 1;	// 1=point 2=brush
		private Color transColor;

		private bool drawPart;
        private bool needQueryBox = false;

		private int endX = 0;
		private int endY = 0;

		private System.Windows.Forms.PictureBox pic;
		private System.Windows.Forms.PictureBox picparts;
		private System.Windows.Forms.PictureBox picmask;
		// ----------------------

		private PictureRegions	objPictureRegions;

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

        #endregion

        #region Constructors and Helpers

        public DrawFindings()
            : base()
        {
            InitializeComponent();
            asm = Assembly.GetCallingAssembly();
            drawPart = false;
        }

		public DrawFindings(Form parent, int left, int top) : base()
		{
			InitializeComponent();
            asm = Assembly.GetCallingAssembly();
            drawPart = false;
			this.Parent = parent;
			this.Left = left;
			this.Top = top;
		}

		private bool createTheRest()
		{
			pic.Left = 0;
			pic.Top = 0;
			this.Width = pic.Width;
			this.Height = pic.Height;

			bitClip = new Bitmap(picmask.Image);
			bitHits = new Bitmap(picmask.Image);
			bitPart = new Bitmap(picparts.Image);
			bitMain = new Bitmap(pic.Image);

			transColor = bitClip.GetPixel(0, 0);
			bitClip.MakeTransparent(transColor);

			pictGraph = Graphics.FromImage(pic.Image);
			maskGraph = Graphics.FromImage(picmask.Image);

			isDrawing = false;
			dotBrush = new SolidBrush(Color.Red);
			panBrush = new SolidBrush(Color.Yellow);
			pen = new Pen(Color.Blue);
			pen.Width = 2;
			mousepoints = new short[2048];	/// good for 1024 points
			ftags = new FindTags(this.Parent, pictGraph, pen, dotBrush, new Rectangle(Left, Top, Width, Height));
			return true;
		}

		private bool CreateDrawing(byte[] ba_draw, byte[] ba_mask, byte[] ba_parts) 
		{
			pic.Image = Image.FromStream(new MemoryStream(ba_draw));
			picparts.Image = Image.FromStream(new MemoryStream(ba_parts));
			picmask.Image = Image.FromStream(new MemoryStream(ba_mask));
			createTheRest();
			return true;
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				//==================
				bitClip.Dispose();
				bitHits.Dispose();
				bitPart.Dispose();
				bitMain.Dispose();
				dotBrush.Dispose();
				panBrush.Dispose();
				pen.Dispose();
				pictGraph.Dispose();
				//==================
				if( components != null )
					components.Dispose();
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.pic = new System.Windows.Forms.PictureBox();
			this.picparts = new System.Windows.Forms.PictureBox();
			this.picmask = new System.Windows.Forms.PictureBox();
			this.SuspendLayout();
			// 
			// pic
			// 
			this.pic.BackColor = System.Drawing.Color.Bisque;
			this.pic.Location = new System.Drawing.Point(56, 40);
			this.pic.Name = "pic";
			this.pic.Size = new System.Drawing.Size(268, 356);
			this.pic.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
			this.pic.TabIndex = 3;
			this.pic.TabStop = false;
			this.pic.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pic_MouseUp);
			this.pic.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pic_MouseMove);
			this.pic.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pic_MouseDown);
			// 
			// picparts
			// 
			this.picparts.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
			this.picparts.Location = new System.Drawing.Point(216, 88);
			this.picparts.Name = "picparts";
			this.picparts.Size = new System.Drawing.Size(268, 356);
			this.picparts.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
			this.picparts.TabIndex = 4;
			this.picparts.TabStop = false;
			this.picparts.Visible = false;
			// 
			// picmask
			// 
			this.picmask.Location = new System.Drawing.Point(56, 216);
			this.picmask.Name = "picmask";
			this.picmask.Size = new System.Drawing.Size(268, 356);
			this.picmask.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
			this.picmask.TabIndex = 5;
			this.picmask.TabStop = false;
			this.picmask.Visible = false;
			// 
			// DrawFindings
			// 
			this.BackColor = System.Drawing.SystemColors.ControlLight;
			this.Controls.Add(this.picmask);
			this.Controls.Add(this.picparts);
			this.Controls.Add(this.pic);
			this.Name = "DrawFindings";
			this.Size = new System.Drawing.Size(512, 472);
			this.Load += new System.EventHandler(this.DrawFindings_Load);
			this.ResumeLayout(false);

		}
		#endregion

        #endregion

        private string StringFromPoints()
		{
			StringBuilder sb = new StringBuilder();
			sb.Append(pointcount);
			for (int n=0,i=0; n<pointcount; n++)
			{
				sb.Append(",");
				sb.Append(mousepoints[i++]);
				sb.Append(" ");
				sb.Append(mousepoints[i++]);
			}
			return sb.ToString();
		}

		private FindTags AddTag(DataRow drow)
		{
			string caption = (string) drow["caption"];
			short xx = (short) drow["x"];
			short yy = (short) drow["y"];
			drow["txtLeft"] = xx + 20;	/// default location
			drow["txtTop"]  = yy - 12;
			drow["kind"] = dType;
			drow["regions"] = regionBits;
			if (dType == 1)
				drawDotPoint(xx, yy, true);
			else if ((dType == 2) || (dType == 3)) // brush and line need points
				drow["points"] = StringFromPoints();
			//--------------------
			FindTags val = ftags.AddTag(drow);
			val.ADraw += new System.EventHandler(this.ReDraw);
			val.Delrow += new System.EventHandler(this.deleteATag);
			val.FindClick += new FindTags.EventFindClick(this.FindTag_Click);
			return val;
		}

		private FindTags ReadFindingRow(DataRow drow, bool visible)
		{
			FindTags val = ftags.AddTag(drow);
			if (visible)
			{
				val.ADraw += new System.EventHandler(this.ReDraw);
				val.Delrow += new System.EventHandler(this.deleteATag);
				val.FindClick += new FindTags.EventFindClick(this.FindTag_Click);
			}
			//-----------------------
			if (val.type == 2)
			{
				short[] pts = val.DrawingPoints;
				int len = pts.Length / 2;
				for (int i=0, n=0; n < len; n++)
				{
					int x = (int) pts[i++];
					int y = (int) pts[i++];
					drawBrushPoint(x, y, false);
				}
			}
			drawDotPoint(val.fx, val.fy, false);
			return val;
		}

		private void ReadFindingRow(DataRow drow)
		{
			short x = (short)drow["x"];
			short y = (short)drow["y"];
			drawDotPoint(x, y, false);
		}

		#region Picture Mouse Events and helper functions

		private bool inBounds(int x, int y)
		{
            if ((x < 0) || (y < 0))
            {
                ReDraw();
                return false;
            }
            if ((x > pic.Size.Width) || (y >= pic.Size.Height))
            {
                ReDraw();
                return false;
            }
			if (bitHits.GetPixel(x, y) != transColor)
				return false;
			return true;
		}

		private void setRegionBits(int x, int y)
		{
			Color c = bitPart.GetPixel(x, y);
			int cint = objPictureRegions.GetRegionId(c);
			regionBits |= cint;
		}

		private void drawBrushPoint(int x, int y, bool inval)
		{
			pictGraph.FillEllipse(panBrush, x-8, y-8, 16, 16);
			if (inval)
			{
				Rectangle r = new Rectangle(x-8, y-8, x+8, y+8);
				pic.Invalidate(r);
			}
        }

		private void drawDotPoint(int x, int y, bool inval)
		{
			pictGraph.FillEllipse(dotBrush, x-4, y-4, 8, 8);
			if (inval)
			{
				Rectangle r = new Rectangle(x-4, y-4, x+4, y+4);
				pic.Invalidate(r);
			}
		}

		private void writeXY(int x, int y)
		{
			int n = pointcount * 2;
			if (n >= mousepoints.Length)
			{
				Trace.WriteLine("PointCount overflow");
				return;
			}
			mousepoints[n++] = (short) x;
			mousepoints[n]   = (short) y;
			pointcount++;
		}

		private void pic_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
            // Determine if a right-click has happened, and if so, toggle query mode
            if (e.Button == MouseButtons.Right)
            {
                base.OnMouseDown(e);
                this.bQueryMode = !this.bQueryMode;
                if (this.bQueryMode)
                    MessageBox.Show("Query mode is enabled.");
                else
                {
                    MessageBox.Show("Query mode is disabled.");
                    this.needQueryBox = false;
                    ReDraw();
                }
                return;
            }

            // If in query mode, let's move to creating a bounding box for the query
            if (bQueryMode)
            {
                startQuery(e.X, e.Y);
                return;
            }

            if (dType == 0)
				return;
			int x = e.X;
			int y = e.Y;
			if (!inBounds(x, y))
				return;
			isDrawing = true;
			drawX = x;
			drawY = y;
			lastX = x;
			lastY = y;
			//Trace.WriteLine(lastX);
			//Trace.WriteLine(lastY);
			pointcount = 0;
            try
            {
                if (!inBounds(x, y))
                    return;
            }
            catch (Exception)
            {
                return;
            }

            Color c = bitPart.GetPixel(x, y);
                int cint = objPictureRegions.GetRegionId(c);
            
			objPictureRegions.ClickRegion = cint;
			regionClick = cint;
			regionBits  = cint;
          
			dType = 1;			// point draw - moving the mouse will change to brush draw
			drawDotPoint(x, y, true);
			writeXY(x, y);
		}

		private void pic_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
		{
            if (e.Button == MouseButtons.Right)
            {
                base.OnMouseMove(e);
                return;
            }

            // Ignore if we are in query mode
            if (bQueryMode)
                return;

            if (!isDrawing)
				return;
			int x = e.X;
			int y = e.Y;
           
            try
            {
                if (!inBounds(x, y))
                    return;
            }
            catch (Exception)
            {
               return;
            }
            
            // did the mouse move more than 2 pixels? 
			bool quantum = (  (x-lastX)*(x-lastX) + (y-lastY)*(y-lastY) > 4 ); 
			if (! quantum)
				return;
			// we are in a brush drawing
            dType = 2;
			lastX = x;
			lastY = y;
			// add this region
           
                Color c = bitPart.GetPixel(x, y);
                int cint = objPictureRegions.GetRegionId(c);
           

			regionBits |= cint;
        	// add this point
			writeXY(x, y);
			drawBrushPoint(x, y, true);
		}

        private void pic_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                base.OnMouseUp(e);
                return;
            }

            // If we're in query mode, let the query box generation finish
            if (bQueryMode)
            {
                endQuery(e.X, e.Y);
                return;
            }

            if (!isDrawing)
                return;
            isDrawing = false;
            endX = e.X;
            endY = e.Y;
            try
            {
                if (!inBounds(endX, endY))
                    return;
            }
            catch (Exception)
            {
                return;
            }

            Color c = bitPart.GetPixel(endX, endY);
            int cint = objPictureRegions.GetRegionId(c);

            objPictureRegions.ClickRegion = cint;


            int n = pointcount * 2;
            if (n >= mousepoints.Length)
            {
                ReDraw();
                return;
            }
            AdidDraw(drawX, drawY, regionBits, regionClick);
            ReDraw();
        }

        private void AdidDraw(int drawX, int drawY, int regionBits, int regionClick)
        {
            string strMenuSelection;
            DialogResult result;

            Guid finding_uid = Guid.NewGuid();

            //if (false == m_IsRepeatSelection)
            //{
            Point p = Cursor.Position;
            FindingSelect fpp = new FindingSelect();
            fpp.Findings = this.captions;
            fpp.Location = new Point(p.X / 2, p.Y / 2);
            DialogResult dres = fpp.ShowDialog();

            if (dres != DialogResult.OK)
            {
                ReDraw();
                return;
            }

            strMenuSelection = fpp.SelectedFinding;

            //int captionIndex = Array.IndexOf(this.forms,strMenuSelection);

            DataRow drow = AppData.ds.Tables[this.GName].NewRow();
            drow["caption"] = strMenuSelection;
            drow["fk"] = this.gid;
            drow["id"] = finding_uid;
            drow["x"] = drawX;
            drow["y"] = drawY;
            drow["regions"] = regionBits;
            drow["diff"] = (byte)1;
            drow["procType"] = this.ProcType.ToString();
            this.AddTag(drow);
            AppData.ds.Tables[this.GName].Rows.Add(drow);


            AppData.CommitRow(this.GName, finding_uid, DMLType.INSERT);
            AppData.ds.Tables[this.GName].AcceptChanges();

           // add_finding(strMenuSelection, drawY, drawY, regionBits, regionClick, finding_uid);
            result = FindClick(strMenuSelection, finding_uid, true);
            if (result != DialogResult.OK)
            {
                AppData.ds.Tables[this.GName].Rows.Remove(drow);
                drow.Delete();
                AppData.DeleteRow(this.GName, finding_uid);
                AppData.ds.Tables[this.GName].AcceptChanges();
                
                             
                
                ReDraw();
                return;
            }
            

            //-----------------------------------------------------------------
            // - the finding dialog tree has added the finding to the datatable
            // - the x,y point is where the user first started drawing
            // - we have a valid finding - draw the tag and add it to the data
            //add_finding(strMenuSelection, drawY, drawY, regionBits, regionClick, finding_uid);
        }

		#endregion

        #region Query Creator Helpers

        private void startQuery(int x, int y)
        {
            this.needQueryBox = true;
            this.drawX = x;
            this.drawY = y;
        }

        private void endQuery(int x, int y)
        {
            this.endX = x;
            this.endY = y;
            ReDraw();
            MessageBox.Show(String.Concat("x BETWEEN ", Math.Min(drawX, endX).ToString(), " AND ",
                Math.Max(drawX, endX).ToString(), " AND y BETWEEN ", Math.Min(drawY, endY).ToString(), " AND ",
                Math.Max(drawY, endY).ToString()));
        }

        private void drawQueryBox()
        {
            pictGraph.DrawRectangle(new Pen(Brushes.MidnightBlue), new Rectangle(
                Math.Min(drawX, endX), Math.Min(drawY, endY), Math.Abs(drawX - endX), Math.Abs(drawY - endY)));
        }

        #endregion

        private void ReDraw(object sender, System.EventArgs e)
		{
			ReDraw();
		}

		private void deleteATag(object sender, System.EventArgs e)
		{
			ReDraw();
		}

		public void ReDraw()
		{
			if (!drawPart)
				pictGraph.DrawImage(bitMain, pic.ClientRectangle);
			else
				pictGraph.DrawImage(bitPart, pic.ClientRectangle);
				//pictGraph.DrawImage(bitMask, pic.ClientRectangle);

			FindTags[] tags = ftags.GetTags();
			for (int n=0; n<tags.Length; n++)
			{
				FindTags t = tags[n];
				if (t.type == 2)  // if brush drawing
				{
					short[] pt = t.DrawingPoints;
					int len = pt.Length / 2;
					for (int j=0, i=0; j<len; j++)
					{
						int x = (int) pt[i++];
						int y = (int) pt[i++];
						drawBrushPoint(x, y, false);
					}
				}
			}
			pictGraph.DrawImage(bitClip, pic.ClientRectangle);			
			ftags.Draw();	// draw all connections
			pic.Invalidate();

            // Draw the query box if it is there and we're in query mode
            if (needQueryBox)
            {
                drawQueryBox();
            }
		}


		private void FindTag_Click(FindTags ftag, Guid fid)
		{
			FindClick(ftag.Text, fid, false);
		}

        private DialogResult FindClick(string p, Guid fid, bool bNew)
        {
            var loc = (new List<string>(captions)).IndexOf(p);
            return LaunchForm(fid, forms[loc], bNew);
        }

        private void add_finding(string caption, int x, int y, int regionGroup, int regionClick, Guid finding_uid)
        {
            DataRow drow = AppData.ds.Tables[this.GName].NewRow();
            drow["caption"] = caption;
            drow["fk"] = this.gid;
            drow["id"] = finding_uid;
            drow["x"] = x;
            drow["y"] = y;
            drow["regions"] = regionGroup;
            drow["diff"] = (byte)1;
            drow["procType"] = this.ProcType.ToString();
            this.AddTag(drow);
            AppData.ds.Tables[this.GName].Rows.Add(drow);
            
           
            AppData.CommitRow(this.GName, finding_uid, DMLType.INSERT);
            AppData.ds.Tables[this.GName].AcceptChanges();
        }

		private void DrawFindings_Load(object sender, System.EventArgs e)
		{
			//Trace.WriteLine("DrawFindings_Load: " + Parent.Name);
			//FindTag.InitClass(this.Parent, pictGraph, pen, dotBrush, new Rectangle(Left, Top, Width, Height));
		}


		public void SaveImage(string filepath)
		{
			//DateTime dt = DateTime.Now;
			/// get resources
			//Bitmap b = new Bitmap(600, 450, pictGraph);
			int w = pic.Width;
			int h = pic.Height;
			Bitmap b = new Bitmap(w*2, h*2, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);

			Image i = Image.FromHbitmap(b.GetHbitmap());
			Graphics g = Graphics.FromImage(i);
			SolidBrush brush = new SolidBrush(Color.White);
			/// draw
			//g.FillRectangle(brush, 1, 1, 598, 448);
			g.FillRectangle(brush, 0, 0, w*2, h*2);
			
			//g.DrawImageUnscaled(pic.Image, x, y);
			g.DrawImage(pic.Image, new Rectangle(0, 0, w*2, h*2), 0, 0, pic.Width, pic.Height,
				GraphicsUnit.Pixel);

			//ftags.Render(g, x, y, 600, 450);
			i.Save(filepath,  System.Drawing.Imaging.ImageFormat.Gif);
			/// free resources
			brush.Dispose();
			g.Dispose();
			i.Dispose();
			b.Dispose();
			//TimeSpan ii = DateTime.Now - dt;
			//MessageBox.Show("Time sec.ms: " + ii.Seconds.ToString() + "." + ii.Milliseconds.ToString());
		}

		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
		{
			if (keyData != Keys.Insert)
				return false;		
			drawPart = ! drawPart;
			ReDraw();
			return true;
		}


        #region Guava Helpers

        string gname;
        Label lab;
        Assembly asm;
        Guid gid;
        DataView dv;

        public System.Windows.Forms.Label Label
        {
            get { return lab; }
            set { lab = value; }
        }

        private string[] forms;
        private string[] captions;
        [Browsable(true), Category("Finding List"),
        Description("Gets/sets the set of findings that the control can launch.  Each item should be in the form \"FormName|Caption\".")]
        public string[] FindingsList
        {
            get
            {
                if (forms == null)
                {
                    forms = new string[] { };
                    captions = new string[] { };
                    return new string[] { };
                }

                var findingslist = new List<string>();
                for (int i = 0; i < forms.Length; i++)
                {
                    findingslist.Add(forms[i] + "|" + captions[i]);
                }
                return findingslist.ToArray();
            }
            set
            {
                var formslist = new List<string>();
                var captionslist = new List<string>();
                foreach (var s in value)
                {
                    var items = s.Split('|');
                    if (items.Length != 2)
                    {
                        throw new Exception("Input items for the Findings List property must be in the form FormName|Caption.");
                    }
                    formslist.Add(items[0]);
                    captionslist.Add(items[1]);
                }

                forms = formslist.ToArray();
                captions = captionslist.ToArray();
            }
        }

        void gf_PersistSignal(object sender, PersistSignalEventArgs e)
        {
            if (e.bPersist) PersistChanges();
            else dv.Table.RejectChanges();
        }

        private void PersistChanges()
        {
            // Purge deleted rows
            dv.RowStateFilter = DataViewRowState.Deleted;
            foreach (DataRowView drv in dv)
                AppData.DeleteRow(dv.Table.TableName, (Guid)drv["id"]);

            // Modify old rows
            dv.RowStateFilter = DataViewRowState.ModifiedCurrent;
            foreach (DataRowView drv in dv)
                AppData.CommitRow(dv.Table.TableName, (Guid)drv["id"], DMLType.UPDATE);

            // Add new rows
            dv.RowStateFilter = DataViewRowState.Added;
            foreach (DataRowView drv in dv)
                AppData.CommitRow(dv.Table.TableName, (Guid)drv["id"], DMLType.INSERT);

            // Finish
            dv.RowStateFilter = DataViewRowState.CurrentRows;
            dv.Table.AcceptChanges();
        }

        #endregion

        #region Guava Members

        [Browsable(false)]
        public LaunchType LType
        {
            get { return LaunchType.Single; }
        }

        [Browsable(false)]
        public ControlType CType
        {
            get { return ControlType.Entity; }
        }

        [Browsable(false)]
        public string GText
        {
            get
            {
                if (this.lab == null) return null;
                return this.lab.Text;
            }
        }

        public string GName
        {
            get
            {
                if (this.gname == null) return this.Name;
                return gname;
            }
            set
            {
                gname = value;
            }
        }

        [Browsable(false)]
        public Point GLocation
        {
            get { return this.Location; }
        }

        [Browsable(false)]
        public Size GSize
        {
            get { return this.Size; }
        }

        [Browsable(false)]
        public System.Collections.Generic.List<Guava> GComponents
        {
            get
            {
                List<Guava> lg = new List<Guava>();
                lg.Add(new GEmpty("caption", new GuavaData.Domain.Enumerated(forms)));
                lg.Add(new GEmpty("points", new GuavaData.Domain.String()));
                lg.Add(new GEmpty("x", new GuavaData.Domain.SmallInteger()));
                lg.Add(new GEmpty("y", new GuavaData.Domain.SmallInteger()));
                lg.Add(new GEmpty("txtLeft", new GuavaData.Domain.SmallInteger()));
                lg.Add(new GEmpty("txtTop", new GuavaData.Domain.SmallInteger()));
                lg.Add(new GEmpty("kind", new GuavaData.Domain.TinyInteger()));
                lg.Add(new GEmpty("regions", new GuavaData.Domain.Integer()));
                lg.Add(new GEmpty("diff", new GuavaData.Domain.TinyInteger()));
                lg.Add(new GEmpty("procType", new GuavaData.Domain.String(5)));
                
                foreach (string s in this.forms)
                {
                    Type t = GLaunchClass.RetrieveTypeFromFile(s, this.asm);
                    if (t == null) continue;
                    ConstructorInfo ci = t.GetConstructor(new Type[] { });
                    Object o = ci.Invoke(new object[] { });
                    lg.Add(o as Guava);
                }

                return lg;
            }
        }

        public void GBind(string table, int i)
        {
            DataRow dr = AppData.ds.Tables[table].Rows[i];
            gid = (Guid)dr["id"];

            // Find parent and attach persistence handler
            GuavaForm gf = this.ParentForm as GuavaForm;
            gf.PersistSignal += new GuavaData.SignalToPersist(gf_PersistSignal);

            // Create a view of the destination table that only has the current ID's
            AppData.FetchRowsByFK(this.GName, gid);
            dv = (new DataView(AppData.ds.Tables[this.GName], "fk='" + gid.ToString() + "'", null, DataViewRowState.CurrentRows));
            dv.AllowNew = true;
            dv.AllowEdit = true;
            dv.AllowDelete = true;

            // Need to actually do the loading of newly-found data into the findings dialog
            foreach (DataRow drow in AppData.ds.Tables[this.GName].Rows)
            {
                if ((string)drow["procType"] != this.ProcType.ToString()) continue;
                this.ReadFindingRow(drow, true);
            }
        }

        [Browsable(false)]
        public string GDefault
        {
            get { return null; }
        }

        [Browsable(false)]
        public string GToolTip
        {
            get
            {
                Control p = this.TopLevelControl;
                if (!(p is Guava)) return null;
                ToolTip t = (p as GuavaForm).GToolTipProvider;
                if (t == null) return null;

                // Fetch the tooltip and return it
                return t.GetToolTip(this);
            }
        }

        [Browsable(false)]
        public GuavaData.Domain.Domain GDomain
        {
            get { return new GuavaData.Domain.UniqueIdentifier(); }
        }

        [Browsable(false)]
        public Guava this[string s]
        {
            get
            {
                foreach (Guava g in this.GComponents) if (g.GName == s) return g;
                return null;
            }
        }

        #endregion

        #region GuavaLaunchBase Members

        public void SetObject(Guid id)
        {
            return;
        }

        public void PrepareStackFrame()
        {
            // Build the seed stack frame call list
            GuavaForm gForm = this.ParentForm as GuavaForm;
            GSeed gsTemp = gForm.GS;
            GSeedFrame gsfTemp = gsTemp.Peek();

            // Create a list of controls
            Control p = this;
            Control q = p.Parent;
            List<string> ls = new List<string>();
            ls.Add(this.GName);

            // Follow parents up the chain to the root form
            while (!(q is GuavaForm))
            {
                if (!(q is Guava))
                {
                    Guava r = q.Parent as Guava;
                    if (r == null) throw new Exception("Found two non-guava objects nested together in the same tree for marking.");
                    bool bfound = false;
                    foreach (Guava g in r.GComponents)
                    {
                        if (g.GComponents.Contains(p as Guava))
                        {
                            ls.Insert(0, g.GName);
                            bfound = true;
                            break;
                        }
                    }
                    if (!bfound) throw new Exception("Could not match a guava object for creating a seed for marking.");
                }
                else ls.Insert(0, (q as Guava).GName);
                p = p.Parent;
                q = q.Parent;
            }
            gsfTemp.controls = ls;
        }

        public DialogResult LaunchForm(Guid gid, string form, bool bNew)
        {
            DialogResult d;

            Type t = GLaunchClass.RetrieveTypeFromFile(form, this.asm);
            if (t == null) return DialogResult.Cancel;

            ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(Guid), typeof(Guid), typeof(bool), typeof(GSeed) });
            GForm o = ci.Invoke(new object[] { gid, gid, bNew, (this.ParentForm as GuavaForm).GS }) as GForm;
            this.PrepareStackFrame();
            d = o.ShowDialog();

            // When done, refresh the items
            ReDraw();
            return d;
        }

        #endregion

        #region GuavaQueryElement Members

        private bool bQueryMode;

        public bool InQueryMode
        {
            get
            {
                return bQueryMode;
            }
            set
            {
                bQueryMode = value;
            }
        }

        public IEnumerable<string> projectColumns
        {
            get { throw new NotImplementedException(); }
        }

        public IEnumerable<string> distinguishedVariables
        {
            get { throw new NotImplementedException(); }
        }

        public IDictionary<string, IEnumerable<Condition>> filterConditions
        {
            get
            {
                Dictionary<string, IEnumerable<Condition>> conds = new Dictionary<string, IEnumerable<Condition>>();
                Condition cx = Condition.NewCondition(ConditionType.BETWEEN, Math.Min(drawX, endX), Math.Max(drawX, endX));
                Condition cy = Condition.NewCondition(ConditionType.BETWEEN, Math.Min(drawY, endY), Math.Max(drawY, endY));

                conds.Add("x", new List<Condition>(new Condition[] { cx }));
                conds.Add("y", new List<Condition>(new Condition[] { cy }));

                return conds;
            }
        }

        public Operator AppendQuery(Operator opIn, Dictionary<string, string> currentProjectColumns)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
